﻿using System;
using System.Data;
using System.Text;
using System.Reflection;
using System.Collections.Generic;

namespace WS.DAL
{
    using IBatisNet.DataMapper;
    using IBatisNet.Common.Utilities;
    using IBatisNet.DataMapper.Configuration;

    public class Mapper
    {
        private static volatile SqlMapper _mapper = null;

        protected static void Configure(object obj)
        {
            _mapper = null;
        }

        protected static void InitMapper()
        {
            var handler = new ConfigureHandler(Configure);
            var builder = new DomSqlMapBuilder();
            _mapper = (SqlMapper)builder.ConfigureAndWatch("Resources/SqlMap.config", handler);
        }

        protected static void InitMapper(string sqlmapconfig)
        {
            var handler = new ConfigureHandler(Configure);
            var builder = new DomSqlMapBuilder();
            _mapper = (SqlMapper)builder.ConfigureAndWatch(sqlmapconfig, handler);
        }

        public static SqlMapper Instance(string sqlmapconfig)
        {
            if (_mapper == null)
            {
                lock (typeof(SqlMapper))
                {
                    if (_mapper == null) // double-check
                    {
                        InitMapper(sqlmapconfig);
                    }
                }
            }

            return _mapper;
        }

        public static SqlMapper Instance()
        {
            if (_mapper == null)
            {
                lock (typeof(SqlMapper))
                {
                    if (_mapper == null) // double-check
                    {
                        InitMapper();
                    }
                }
            }

            return _mapper;
        }

        public static SqlMapper Get()
        {
            return Instance();
        }

        public static SqlMapper Get(string sqlmapconfig)
        {
            return Instance(sqlmapconfig);
        }

        public static DataTable QueryForDataTable(string statementName, object parameterObject, string tableName = "Tmp")
        {
            var session = _mapper.CreateSqlMapSession();
            var statement = _mapper.GetMappedStatement(statementName);
            var dataTable = new DataTable(tableName);

            var request = statement.Statement.Sql.GetRequestScope(statement, parameterObject, session);
            statement.PreparedCommand.Create(request, session, statement.Statement, parameterObject);

            using (request.IDbCommand)
            {
                dataTable.Load(request.IDbCommand.ExecuteReader(CommandBehavior.KeyInfo));
            }

            return dataTable;
        }

        public static DataSet QueryForDataSet(string statementName, object parameterObject = null)
        {
            try
            {
                var ds = new DataSet();
                var dataTable = Mapper.QueryForDataTable(statementName, parameterObject);
                ds.Tables.Add(dataTable);

                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

    public struct QueryIDs
    {
        public string Select;
        public string Insert;
        public string Update;
        public string Delete;
    }
}